package swing;

import java.awt.*;
import java.awt.event.*;
import java.awt.geom.*;
import java.net.*;
import java.applet.*;
import java.util.LinkedList;
import java.util.Iterator;
import javax.swing.*;
import javax.swing.undo.*;
/**
 * A very simple applet demonstrating usage of javax.swing.undo package.
 */
public class undomgrtest extends JApplet {

    JButton linebutton;
    JButton circlebutton;
    JButton undobutton;
    JButton redobutton;
    JPanel buttonpanel;
    JGraphPanel graphpanel;
    LineListener linelistener;
    CircleListener circlelistener;
    UndoListener undolistener;
    RedoListener redolistener;
    LinkedList shapes;
    UndoManager undomgr;

    public void init() {

	// Force SwingApplet to come up in the System L&F
	String laf = UIManager.getSystemLookAndFeelClassName();
	try {
	    UIManager.setLookAndFeel(laf);
	    // If you want the Cross Platform L&F instead, comment out the above line and
	    // uncomment the following:
	    // UIManager.setLookAndFeel(UIManager.getCrossPlatformLookAndFeelClassName());
	} catch (UnsupportedLookAndFeelException exc) {
	    System.err.println("Warning: UnsupportedLookAndFeel: " + laf);
	} catch (Exception exc) {
	    System.err.println("Error loading " + laf + ": " + exc);
	}

    getContentPane().setLayout(new BorderLayout());
    linebutton = new JButton("Draw Line");
	circlebutton = new JButton("Draw Circle");
	undobutton = new JButton("Undo");
	redobutton = new JButton("Redo");
	graphpanel = new JGraphPanel(false);
	graphpanel.setPreferredSize(new Dimension(300,300));
	buttonpanel = new JPanel(false);
	buttonpanel.setLayout(new FlowLayout());
	buttonpanel.add(linebutton);
    buttonpanel.add(circlebutton);
	buttonpanel.add(undobutton);
	buttonpanel.add(redobutton);
	getContentPane().add(buttonpanel,BorderLayout.SOUTH);
	getContentPane().add(graphpanel,BorderLayout.NORTH);
	linelistener = new LineListener();
	linebutton.addActionListener(linelistener);
	circlelistener = new CircleListener();
	circlebutton.addActionListener(circlelistener);
	undolistener = new UndoListener();
	undobutton.addActionListener(undolistener);
	redolistener = new RedoListener();
	redobutton.addActionListener(redolistener);
	shapes = new LinkedList();
	undomgr = new UndoManager();
    }

    public void stop() {

    }
    class JGraphPanel extends JPanel{
	public JGraphPanel(boolean doublebuffer)
	{
	    super(doublebuffer);
	}
	public void paintComponent(Graphics g) {
	    Graphics2D g2 = (Graphics2D)g;
	    g2.setColor(Color.white);
	    g2.fill3DRect(0,0,getWidth(),getHeight(),true);
	    Iterator it;
	    Shape shape;
	    g2.setColor(Color.black);
	    for(it = shapes.iterator();it.hasNext();){
		shape = (Shape)it.next();
		g2.draw(shape);
	    }
	}
    }
    class LineListener implements ActionListener{
	Shape temp;
	public void actionPerformed(ActionEvent e){
	    temp = new Line2D.Double(0.0,0.0,Math.random()*100.0,Math.random()*100.0);
	    shapes.add(temp);
	    repaint();
	    UndoableEdit edit = new graphEdit(temp);
	    undomgr.addEdit(edit);
	}
    }
    class CircleListener implements ActionListener{
	Shape temp;
	public void actionPerformed(ActionEvent e){
	    temp = new Ellipse2D.Double(0.0,0.0,Math.random()*100.0,Math.random()*100.0);
	    shapes.add(temp);
	    repaint();
	    UndoableEdit edit = new graphEdit(temp);
	    undomgr.addEdit(edit);

	}
    }
    class UndoListener implements ActionListener{
	public void actionPerformed(ActionEvent e){
	    try{
		undomgr.undo();
	    }catch(CannotUndoException ex){
		System.err.println("Can't Undo More");
	    }
	}
    }
    class RedoListener implements ActionListener{
	public void actionPerformed(ActionEvent e){
	    try{
		undomgr.redo();
	    }catch(CannotRedoException ex){
		System.err.println("Can't Redo More");
	    }
	}
    }

    class graphEdit extends AbstractUndoableEdit{
	Shape shape;
	public graphEdit(Shape _shape){
	    shape = _shape;
	}
	public void undo(){
	    shapes.remove(shape);
	    repaint();
	    System.out.println("undo draw line");
	}
	public void redo(){
	    shapes.add(shape);
	    repaint();
	    System.out.println("redo draw line");
	}
    }
}
